package com.sena.engine.snmp.base;

import com.sena.engine.snmp.config.DefaultConstant;
import com.sena.engine.snmp.config.SnmpSysConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.*;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;

public class SnmpCommunication {

    private static final Logger log = LoggerFactory.getLogger(SnmpCommunication.class);

    public static final String DEFAULT_PROTOCOL = "udp";


    public static Snmp createSnmp(SnmpTarget target) throws IOException {
        Snmp snmp = null;
        //1、初始化多线程消息转发类
        MessageDispatcher messageDispatcher = new MessageDispatcherImpl();
        //其中要增加三种处理模型。如果snmp初始化使用的是Snmp(TransportMapping<? extends Address> transportMapping) ,就不需要增加
        messageDispatcher.addMessageProcessingModel(new MPv1());
        messageDispatcher.addMessageProcessingModel(new MPv2c());
        //当要支持snmpV3版本时，需要配置user
        if (target.getSnmpVersion() == SnmpConstants.version3) {
            USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
            UsmUser user = new UsmUser(
                    new OctetString("SNMPV3"),
                    AuthSHA.ID,
                    new OctetString(target.getV3AuthPasswd()),
                    PrivAES128.ID,
                    new OctetString(target.getV3PrivacyPasswd()));
            usm.addUser(user.getSecurityName(), user);
            messageDispatcher.addMessageProcessingModel(new MPv3(usm));
        }
        //2、创建transportMapping
        TransportMapping transportMapping = new DefaultUdpTransportMapping();
        //3、正式创建snmp
        snmp = new Snmp(messageDispatcher, transportMapping);
        //开启监听
        snmp.listen();
        return snmp;
    }





    public static PDU createPdu(int version) {
        PDU pdu = null;
        if (version == SnmpConstants.version3) {
            pdu = new ScopedPDU();
        } else {
            pdu = new PDUv1();
        }
        return pdu;
    }

    //2.创建目标地址对象
    public static Target getTarget(SnmpTarget snmpTarget, int targetType) {

        if (!(snmpTarget.getSnmpVersion() == SnmpConstants.version3 ||
                snmpTarget.getSnmpVersion() == SnmpConstants.version2c ||
                snmpTarget.getSnmpVersion() == SnmpConstants.version1)) {
            log.error("snmp设置版本号异常");
            return null;
        }
        Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + snmpTarget.getNodeIP() + "/" + snmpTarget.getPort());
        if (snmpTarget.getSnmpVersion() == SnmpConstants.version3) {
            UserTarget target = new UserTarget();
            //IP+Port
            target.setAddress(address);
            //Version
            target.setVersion(snmpTarget.getSnmpVersion());
            //timeout
            target.setTimeout(snmpTarget.getTargetSnmpTimeout() == 0L ? SnmpSysConfig.SNMP_TIMEOUT : snmpTarget.getTargetSnmpTimeout());
            //Retries
            target.setRetries(snmpTarget.getTargetSnmpRetry() == 0 ? SnmpSysConfig.SNMP_RETRY : snmpTarget.getTargetSnmpRetry());

            target.setSecurityLevel(snmpTarget.getV3SecurityLevel());
            target.setSecurityName(new OctetString(snmpTarget.getV3User()));
            target.setSecurityModel(snmpTarget.getV3PrivacyProtocol());
            return target;
        } else {
            CommunityTarget target = new CommunityTarget();
            //IP+Port
            target.setAddress(address);
            //Version
            target.setVersion(snmpTarget.getSnmpVersion());
            //Community
            //targetType  1:SET  0：GET
            if (targetType == DefaultConstant.SNMP_COMMUNITY_SET) {
                target.setCommunity(new OctetString(snmpTarget.getWriteCommunity()));
            } else {
                target.setCommunity(new OctetString(snmpTarget.getReadCommunity()));
            }
            target.setTimeout(snmpTarget.getTargetSnmpTimeout() == 0L ? SnmpSysConfig.SNMP_TIMEOUT : snmpTarget.getTargetSnmpTimeout());
            //Retries
            target.setRetries(snmpTarget.getTargetSnmpRetry() == 0 ? SnmpSysConfig.SNMP_RETRY : snmpTarget.getTargetSnmpRetry());
            return target;
        }
    }


}
